#ifndef THINK_THINK_EXCEPTION_HANDLE_H
#define THINK_THINK_EXCEPTION_HANDLE_H

static char* think_exception_handle =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: yunwuxin <448901948@qq.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think\\exception;\n"
	"\n"
	"use Exception;\n"
	"use think\\App;\n"
	"use think\\Config;\n"
	"use think\\console\\Output;\n"
	"use think\\Lang;\n"
	"use think\\Log;\n"
	"use think\\Response;\n"
	"\n"
	"class Handle\n"
	"{\n"
	"    protected $render;\n"
	"    protected $ignoreReport = [\n"
	"        \'\\\\think\\\\exception\\\\HttpException\',\n"
	"    ];\n"
	"\n"
	"    public function setRender($render)\n"
	"    {\n"
	"        $this->render = $render;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * Report or log an exception.\n"
	"     *\n"
	"     * @param  \\Exception $exception\n"
	"     * @return void\n"
	"     */\n"
	"    public function report(Exception $exception)\n"
	"    {\n"
	"        if (!$this->isIgnoreReport($exception)) {\n"
	"            // 收集异常数据\n"
	"            if (App::$debug) {\n"
	"                $data = [\n"
	"                    \'file\'    => $exception->getFile(),\n"
	"                    \'line\'    => $exception->getLine(),\n"
	"                    \'message\' => $this->getMessage($exception),\n"
	"                    \'code\'    => $this->getCode($exception),\n"
	"                ];\n"
	"                $log = \"[{$data[\'code\']}]{$data[\'message\']}[{$data[\'file\']}:{$data[\'line\']}]\";\n"
	"            } else {\n"
	"                $data = [\n"
	"                    \'code\'    => $this->getCode($exception),\n"
	"                    \'message\' => $this->getMessage($exception),\n"
	"                ];\n"
	"                $log = \"[{$data[\'code\']}]{$data[\'message\']}\";\n"
	"            }\n"
	"\n"
	"            if (Config::get(\'record_trace\')) {\n"
	"                $log .= \"\\r\\n\" . $exception->getTraceAsString();\n"
	"            }\n"
	"\n"
	"            Log::record($log, \'error\');\n"
	"        }\n"
	"    }\n"
	"\n"
	"    protected function isIgnoreReport(Exception $exception)\n"
	"    {\n"
	"        foreach ($this->ignoreReport as $class) {\n"
	"            if ($exception instanceof $class) {\n"
	"                return true;\n"
	"            }\n"
	"        }\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * Render an exception into an HTTP response.\n"
	"     *\n"
	"     * @param  \\Exception $e\n"
	"     * @return Response\n"
	"     */\n"
	"    public function render(Exception $e)\n"
	"    {\n"
	"        if ($this->render && $this->render instanceof \\Closure) {\n"
	"            $result = call_user_func_array($this->render, [$e]);\n"
	"            if ($result) {\n"
	"                return $result;\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if ($e instanceof HttpException) {\n"
	"            return $this->renderHttpException($e);\n"
	"        } else {\n"
	"            return $this->convertExceptionToResponse($e);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * @param Output    $output\n"
	"     * @param Exception $e\n"
	"     */\n"
	"    public function renderForConsole(Output $output, Exception $e)\n"
	"    {\n"
	"        if (App::$debug) {\n"
	"            $output->setVerbosity(Output::VERBOSITY_DEBUG);\n"
	"        }\n"
	"        $output->renderException($e);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * @param HttpException $e\n"
	"     * @return Response\n"
	"     */\n"
	"    protected function renderHttpException(HttpException $e)\n"
	"    {\n"
	"        $status   = $e->getStatusCode();\n"
	"        $template = Config::get(\'http_exception_template\');\n"
	"        if (!App::$debug && !empty($template[$status])) {\n"
	"            return Response::create($template[$status], \'view\', $status)->assign([\'e\' => $e]);\n"
	"        } else {\n"
	"            return $this->convertExceptionToResponse($e);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * @param Exception $exception\n"
	"     * @return Response\n"
	"     */\n"
	"    protected function convertExceptionToResponse(Exception $exception)\n"
	"    {\n"
	"        // 收集异常数据\n"
	"        if (App::$debug) {\n"
	"            // 调试模式，获取详细的错误信息\n"
	"            $data = [\n"
	"                \'name\'    => get_class($exception),\n"
	"                \'file\'    => $exception->getFile(),\n"
	"                \'line\'    => $exception->getLine(),\n"
	"                \'message\' => $this->getMessage($exception),\n"
	"                \'trace\'   => $exception->getTrace(),\n"
	"                \'code\'    => $this->getCode($exception),\n"
	"                \'source\'  => $this->getSourceCode($exception),\n"
	"                \'datas\'   => $this->getExtendData($exception),\n"
	"                \'tables\'  => [\n"
	"                    \'GET Data\'              => $_GET,\n"
	"                    \'POST Data\'             => $_POST,\n"
	"                    \'Files\'                 => $_FILES,\n"
	"                    \'Cookies\'               => $_COOKIE,\n"
	"                    \'Session\'               => isset($_SESSION) ? $_SESSION : [],\n"
	"                    \'Server/Request Data\'   => $_SERVER,\n"
	"                    \'Environment Variables\' => $_ENV,\n"
	"                    \'ThinkPHP Constants\'    => $this->getConst(),\n"
	"                ],\n"
	"            ];\n"
	"        } else {\n"
	"            // 部署模式仅显示 Code 和 Message\n"
	"            $data = [\n"
	"                \'code\'    => $this->getCode($exception),\n"
	"                \'message\' => $this->getMessage($exception),\n"
	"            ];\n"
	"\n"
	"            if (!Config::get(\'show_error_msg\')) {\n"
	"                // 不显示详细错误信息\n"
	"                $data[\'message\'] = Config::get(\'error_message\');\n"
	"            }\n"
	"        }\n"
	"\n"
	"        //保留一层\n"
	"        while (ob_get_level() > 1) {\n"
	"            ob_end_clean();\n"
	"        }\n"
	"\n"
	"        $data[\'echo\'] = ob_get_clean();\n"
	"\n"
	"        ob_start();\n"
	"        extract($data);\n"
	"        include Config::get(\'exception_tmpl\');\n"
	"        // 获取并清空缓存\n"
	"        $content  = ob_get_clean();\n"
	"        $response = new Response($content, \'html\');\n"
	"\n"
	"        if ($exception instanceof HttpException) {\n"
	"            $statusCode = $exception->getStatusCode();\n"
	"            $response->header($exception->getHeaders());\n"
	"        }\n"
	"\n"
	"        if (!isset($statusCode)) {\n"
	"            $statusCode = 500;\n"
	"        }\n"
	"        $response->code($statusCode);\n"
	"        return $response;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取错误编码\n"
	"     * ErrorException则使用错误级别作为错误编码\n"
	"     * @param  \\Exception $exception\n"
	"     * @return integer                错误编码\n"
	"     */\n"
	"    protected function getCode(Exception $exception)\n"
	"    {\n"
	"        $code = $exception->getCode();\n"
	"        if (!$code && $exception instanceof ErrorException) {\n"
	"            $code = $exception->getSeverity();\n"
	"        }\n"
	"        return $code;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取错误信息\n"
	"     * ErrorException则使用错误级别作为错误编码\n"
	"     * @param  \\Exception $exception\n"
	"     * @return string                错误信息\n"
	"     */\n"
	"    protected function getMessage(Exception $exception)\n"
	"    {\n"
	"        $message = $exception->getMessage();\n"
	"        if (IS_CLI) {\n"
	"            return $message;\n"
	"        }\n"
	"\n"
	"        if (strpos($message, \':\')) {\n"
	"            $name    = strstr($message, \':\', true);\n"
	"            $message = Lang::has($name) ? Lang::get($name) . strstr($message, \':\') : $message;\n"
	"        } elseif (strpos($message, \',\')) {\n"
	"            $name    = strstr($message, \',\', true);\n"
	"            $message = Lang::has($name) ? Lang::get($name) . \':\' . substr(strstr($message, \',\'), 1) : $message;\n"
	"        } elseif (Lang::has($message)) {\n"
	"            $message = Lang::get($message);\n"
	"        }\n"
	"        return $message;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取出错文件内容\n"
	"     * 获取错误的前9行和后9行\n"
	"     * @param  \\Exception $exception\n"
	"     * @return array                 错误文件内容\n"
	"     */\n"
	"    protected function getSourceCode(Exception $exception)\n"
	"    {\n"
	"        // 读取前9行和后9行\n"
	"        $line  = $exception->getLine();\n"
	"        $first = ($line - 9 > 0) ? $line - 9 : 1;\n"
	"\n"
	"        try {\n"
	"            $contents = file($exception->getFile());\n"
	"            $source   = [\n"
	"                \'first\'  => $first,\n"
	"                \'source\' => array_slice($contents, $first - 1, 19),\n"
	"            ];\n"
	"        } catch (Exception $e) {\n"
	"            $source = [];\n"
	"        }\n"
	"        return $source;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取异常扩展信息\n"
	"     * 用于非调试模式html返回类型显示\n"
	"     * @param  \\Exception $exception\n"
	"     * @return array                 异常类定义的扩展数据\n"
	"     */\n"
	"    protected function getExtendData(Exception $exception)\n"
	"    {\n"
	"        $data = [];\n"
	"        if ($exception instanceof \\think\\Exception) {\n"
	"            $data = $exception->getData();\n"
	"        }\n"
	"        return $data;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取常量列表\n"
	"     * @return array 常量列表\n"
	"     */\n"
	"    private static function getConst()\n"
	"    {\n"
	"        return get_defined_constants(true)[\'user\'];\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif